package com.hjjt.cameralib

import android.app.Application
import android.content.Context
import android.os.Environment
import android.util.Log
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.hjjt.cameralib.fragment.GLSurfaceFragment
import com.hjjt.cameralib.fragment.PermissionFragment
import com.hjjt.cameralib.utils.SoLoadUtil
import com.hjjt.cameralib.utils.TinkerLoadLibrary
import com.hjjt.cameraplugin.CameraEngineConfig
import com.hjjt.cameraplugin.CameraHelper
import com.hjjt.cameraplugin.ImageData
import com.hjjt.filelib.FileUtil
import com.hjjt.logger.logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
import java.lang.ref.WeakReference


class CameraHelperImpl : CameraHelper {

    companion object {
        var cameraInit = false
        var cameraOpenSuccess: (() -> Unit)? = null
        var cameraStartDetect: (() -> Unit)? = null
        var cameraOpenError: ((funName: String, code: Int) -> Unit)? = null

    }

    var glFragment: GLSurfaceFragment? = null
    var cameraSoPath =
        Environment.getExternalStorageDirectory().absolutePath + File.separator + Environment.DIRECTORY_DOWNLOADS + File.separator + "cw_lib" + File.separator + "armeabi-v7a"

    override fun openCamera(
        cameraEngineType: CameraEngineConfig.CameraEngineType,
        activity: FragmentActivity,
        parentViewId: Int,
        angle: CameraEngineConfig.Angle,
        callBack: (code: Int, msg: String, data: ImageData?) -> Unit
    ) {
        Log.e("CameraHelperImpl", "so ：${cameraSoPath}")

        var dirFile = File(activity.getDir("libs", Application.MODE_PRIVATE), "camera")
        if (!dirFile.exists()) {
            dirFile.mkdirs()
        }
        var allSoExit = true
        SoLoadUtil.cloudWalkPath.forEach {
            val exists = File(it).exists()
            if (!exists) {
                allSoExit = false
            }
        }
        if (allSoExit) {
            logger?.e("so 文件存在，直接打开摄像头")
            openCameraActivity(activity, dirFile, cameraEngineType, angle, parentViewId, callBack)
            return
        }
        val copyTime = System.currentTimeMillis()
        FileUtil.copyAllDir(
            cameraSoPath,
            dirFile.absolutePath
        ) { success, failedPathList, successList ->
            if (success) {
                val copySuccessCompletedTime = System.currentTimeMillis()
                logger?.e("文件复制耗时${copySuccessCompletedTime - copyTime}毫秒")

                openCameraActivity(
                    activity,
                    dirFile,
                    cameraEngineType,
                    angle,
                    parentViewId,
                    callBack
                )
            } else {
                logger?.e("so 文件复制失败，摄像头打开失败")
            }
        }

    }


    override fun openCamera(
        cameraEngineType: CameraEngineConfig.CameraEngineType,
        fragment: Fragment,
        parentViewId: Int,
        angle: CameraEngineConfig.Angle,
        callBack: (code: Int, msg: String, data: ImageData?) -> Unit
    ) {
        val dirFile =
            File(fragment.requireActivity().getDir("libs", Application.MODE_PRIVATE), "camera")
        if (!dirFile.exists()) {
            dirFile.mkdirs()
        }
        var allSoExit = true
        SoLoadUtil.cloudWalkPath.forEach {
            val exists = File(it).exists()
            if (!exists) {
                allSoExit = false
            }
        }
        if (allSoExit) {
            logger?.e("so 文件存在，直接打开摄像头")
            openCameraFragment(fragment, dirFile, cameraEngineType, angle, parentViewId, callBack)
            return
        }
        val copyTime = System.currentTimeMillis()
        FileUtil.copyAllDir(
            cameraSoPath,
            dirFile.absolutePath
        ) { success, failedPathList, successList ->
            if (success) {
                val copySuccessCompletedTime = System.currentTimeMillis()
                logger?.e("文件复制耗时${copySuccessCompletedTime - copyTime}毫秒")
                openCameraFragment(
                    fragment,
                    dirFile,
                    cameraEngineType,
                    angle,
                    parentViewId,
                    callBack
                )
            } else {
                logger?.e("so 文件复制失败，摄像头打开失败")
            }
        }

    }


    /**
     * activity内打开相机.
     *
     * @param activity Activity
     * @param dirFile 私有目录文件夹
     * @param cameraEngineType 相机类型
     * @param angle 旋转
     * @param parentViewId Parent 父布局ID
     */
    private fun openCameraActivity(
        activity: FragmentActivity,
        dirFile: File,
        cameraEngineType: CameraEngineConfig.CameraEngineType,
        angle: CameraEngineConfig.Angle,
        parentViewId: Int,
        callBack: (code: Int, msg: String, data: ImageData?) -> Unit
    ) {
        TinkerLoadLibrary.installNativeLibraryPath(activity.classLoader, dirFile)
        SoLoadUtil.loadCameraSo(cameraEngineType)
        glFragment = GLSurfaceFragment.newInstance(
            cameraEngineType,
            angle
        )

        val fm = activity.supportFragmentManager.beginTransaction()
        var permissionFragment: PermissionFragment? = null
        permissionFragment = PermissionFragment() { allGranted, grantedList, deniedList ->
            activity.supportFragmentManager.beginTransaction().run {
                CameraInstance.instance.initCallBack(callBack)
                add(parentViewId, glFragment!!).commit()
            }
        }
        fm.add(permissionFragment, "cameraPermission").commitNow()
        permissionFragment.requestPermission()
    }

    /**
     * 在fragment中打开相机.
     *
     * @param fragment Fragment
     * @param dirFile 私有目录文件夹
     * @param cameraEngineType 相机类型
     * @param angle 旋转
     * @param parentViewId Parent 父布局ID
     */
    private fun openCameraFragment(
        fragment: Fragment,
        dirFile: File,
        cameraEngineType: CameraEngineConfig.CameraEngineType,
        angle: CameraEngineConfig.Angle,
        parentViewId: Int,
        callBack: (code: Int, msg: String, data: ImageData?) -> Unit
    ) {
        TinkerLoadLibrary.installNativeLibraryPath(fragment.requireActivity().classLoader, dirFile)
        SoLoadUtil.loadCameraSo(cameraEngineType)
        glFragment = GLSurfaceFragment.newInstance(
            cameraEngineType,
            angle
        )
        val fm = fragment.childFragmentManager.beginTransaction()
        var permissionFragment: PermissionFragment? = null
        permissionFragment = PermissionFragment() { allGranted, grantedList, deniedList ->
            fragment.childFragmentManager.beginTransaction().apply {
                CameraInstance.instance.initCallBack(callBack)
                add(parentViewId, glFragment!!).commit()
            }
        }
        fm.add(permissionFragment, "cameraPermission").commitNow()
        permissionFragment.requestPermission()
    }

    override fun captureImage(
        isBase64: Boolean,
        timeout: Long,
        callBack: (image: ImageData) -> Unit,
        errorCallBack: () -> Unit
    ) {
        GlobalScope.launch(Dispatchers.Main) {
//            glFragment?.captureImage(isBase64, timeout, callBack, errorCallBack)
        }
    }

    override fun closeCamera() {
        GlobalScope.launch(Dispatchers.Main) {
//            glFragment?.closeCamera()
        }
    }

}